package com.pandora.common.HttpRequest;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;

import android.util.Log;

import com.pandora.common.Utils.base64.Base64Coder;

public abstract class Post extends Req {
	protected static final boolean DEBUG = false;

	protected abstract String getUrl();
	protected final ArrayList<BasicNameValuePair> mEntities = new ArrayList<BasicNameValuePair>(5);
	protected final  MultipartEntity mPartEntities = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE,null, Charset.forName("UTF-8"));
	
	
	protected void addEntity(String name, String value) {
		mEntities.add(new BasicNameValuePair(name, value));
	}
	
	protected void addEntity(String name, ContentBody value) {
		mPartEntities.addPart(name, value);
	}
	
	protected void addMultiPartEntity ( HashMap<String, ContentBody> entity) {
		if (false == entity.isEmpty())
		{
			final Iterator<Entry<String, ContentBody>> iter = entity.entrySet().iterator();
			while(iter.hasNext())
			{
				final Entry<String, ContentBody> entry = iter.next();;
				mPartEntities.addPart(entry.getKey(), entry.getValue());
			}
		}
	}
	
	protected int mConnectionTimeout, mSoTimeout;
	public void setTimeout(int timeout) {
		mConnectionTimeout = mSoTimeout = timeout;
	}

	public void setTimeout(int connection_timeout, int so_timeout) {
		mConnectionTimeout = connection_timeout;
		mSoTimeout = so_timeout;
	}

	public HttpResponse Request() throws IOException, ConnectException
	{
		HttpClient client = new DefaultHttpClient();
		if (null != client)
		{
			if (0 != mConnectionTimeout || 0 != mSoTimeout)
			{	
				HttpParams params = client.getParams();
				HttpConnectionParams.setConnectionTimeout(params, mConnectionTimeout);
				HttpConnectionParams.setSoTimeout(params, mSoTimeout);
			}
			
			try
			{
				Log.i("CH_DEBUG", getUrl());
				HttpPost post = new HttpPost(this.getUrl());
				if (null != post)
				{
					if (//null != mEntities && 
						false == mEntities.isEmpty())
						post.setEntity(new UrlEncodedFormEntity(mEntities, HTTP.UTF_8));
					
					return client.execute(post);
				}
			}
			catch(IllegalArgumentException e)
			{
				if (DEBUG)
					e.printStackTrace();
			}
			catch(UnsupportedEncodingException e)
			{
				if (DEBUG)
					e.printStackTrace();
			}
			catch(ClientProtocolException e)
			{
				if (DEBUG)
					e.printStackTrace();
			}
			finally
			{
			//post.abort();
			}
		}
		
		return null;
	}
	
	public HttpResponse RequestFile() throws IOException
	{
		HttpClient client = new DefaultHttpClient();
		if (null != client)
		{
			if (0 != mConnectionTimeout || 0 != mSoTimeout)
			{
				HttpParams params = client.getParams();
				HttpConnectionParams.setConnectionTimeout(params, mConnectionTimeout);
				HttpConnectionParams.setSoTimeout(params, mSoTimeout);
			}
			
			try
			{
				HttpPost post = new HttpPost(this.getUrl());
				post.setHeader("Connection", "Keep-Alive");
			    post.setHeader("Accept-Charset", "UTF-8");
				post.setHeader("ENCTYPE", "multipart/form-data");

				if (null != post)
				{
					post.setEntity(mPartEntities);
					return client.execute(post);
				}
			}
			catch(IllegalArgumentException e)
			{
				if (DEBUG)
					e.printStackTrace();
			}
			catch(UnsupportedEncodingException e)
			{
				if (DEBUG)
					e.printStackTrace();
			}
			catch(ClientProtocolException e)
			{
				if (DEBUG)
					e.printStackTrace();
			}
			finally
			{
			//post.abort();
			}
		}
		
		return null;
	}

	public boolean Cancel()
	{
		return false;
	}

	public static String encodeBase64(String string)
	{
		return Base64Coder.encodeString(string);
	}
//*/
	static final String CDATA_PREFIX = "<![CDATA[";
	static final String CDATA_SUFFIX = "]]>";
	static final int LENGTH_CDATA_PREFIX = CDATA_PREFIX.length();
	static final int LENGTH_CDATA_SUFFIX = CDATA_SUFFIX.length();
	public static String decodeCDATA(String string)
	{
		if (string.startsWith(CDATA_PREFIX))
			return string.substring(LENGTH_CDATA_PREFIX, string.length() - LENGTH_CDATA_SUFFIX);
		else
			return string;
	}
	
	public static class Parameters {
		
		public String toString() {
			String to = "";
			if (false == mMap.isEmpty())
			{
				StringBuilder param = new StringBuilder(100);
				param.append("<" + mTag + "><");
				final Iterator<Entry<String, String> > iter = mMap.entrySet().iterator();
				while(iter.hasNext())
				{
					final Entry<String, String> entry = iter.next();;
					final String name = entry.getKey();
					param.append(name).append(">").append(entry.getValue()).append("</").append(name).append("><");
				}
				
				to = param.append("/" + mTag + ">").toString();
			}
			
			return to;
		}
		
		public Parameters addParameter(String name, String value) {
			mMap.put(name, value);
			return this;
		}
		
		public Parameters(String tag) {
			mTag = tag;
		}
		
		public Parameters() {
			this("PARAMETER");
		}
		
		protected final String mTag;
		protected final HashMap<String, String> mMap = new HashMap<String, String>();
	}
	
	public static class FileParameters {
		protected final HashMap<String, ContentBody> mMap = new HashMap<String, ContentBody>();
		public FileParameters addParameter(String name, Object value) {
			ContentBody contentBody = null;
			try {
				if( null != value) {
					if ( value instanceof String ) {
						contentBody = new StringBody((String) value, Charset.forName("UTF-8"));
					} else {
						if (value instanceof File )
							contentBody = new FileBody((File) value);
						/*else {
							mMap.put(name, contentBody);
						}*/
					}
					
					if ( contentBody != null ) {
						mMap.put(name, contentBody);
					}
				}
			} catch (Exception e) {
			}
			
			return this;
		}
		
		public HashMap<String, ContentBody> getContentBody() {
			return this.mMap;
		}
	}
	
}